package com.tabjin.rfidsocket.service.sys.impl;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.tabjin.rfidsocket.common.RequestHolder;
import com.tabjin.rfidsocket.common.enums.ProjectBuildingUserStatusEnum;
import com.tabjin.rfidsocket.common.enums.UserStatusEnum;
import com.tabjin.rfidsocket.common.utils.BeanValidator;
import com.tabjin.rfidsocket.common.utils.MD5Util;
import com.tabjin.rfidsocket.common.utils.PagedGridResult;
import com.tabjin.rfidsocket.common.utils.PasswordUtil;
import com.tabjin.rfidsocket.exception.ParamException;
import com.tabjin.rfidsocket.mapper.mapper.ArchProjectBuildingUserMapper;
import com.tabjin.rfidsocket.mapper.mapper.ArchProjectMapper;
import com.tabjin.rfidsocket.mapper.mapper.SysUserCustomMapper;
import com.tabjin.rfidsocket.mapper.mapper.SysUserMapper;
import com.tabjin.rfidsocket.pojo.ArchProject;
import com.tabjin.rfidsocket.pojo.ArchProjectBuildingUser;
import com.tabjin.rfidsocket.pojo.SysUser;
import com.tabjin.rfidsocket.pojo.bo.SysUserBO;
import com.tabjin.rfidsocket.pojo.bo.WxRegisterBO;
import com.tabjin.rfidsocket.pojo.vo.SysUserVO;
import com.tabjin.rfidsocket.pojo.vo.UserVO;
import com.tabjin.rfidsocket.service.sys.SysUserService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author tabjin
 * create at 2020/12/9 16:53
 * @program rfid_socket
 * @description
 */
@Service
public class SysUserServiceImpl implements SysUserService {

    @Value("${wx.app-id}")
    private String appId;

    @Value("${wx.app-secret}")
    private String appSecret;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysUserCustomMapper sysUserCustomMapper;

    @Autowired
    private ArchProjectBuildingUserMapper archProjectBuildingUserMapper;

    @Autowired
    private ArchProjectMapper archProjectMapper;

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public SysUserVO add(SysUserBO sysUserBO) {
        BeanValidator.check(sysUserBO);
        if (checkTelephoneExist(sysUserBO.getTelephone(), sysUserBO.getId())) {
            throw new ParamException("移动电话已被占用");
        }
        if (checkEmailExist(sysUserBO.getMail(), sysUserBO.getId())) {
            throw new ParamException("邮箱已被占用");
        }
        // TODO 这边暂时给定密码
        String password = PasswordUtil.randomPassword();
        password = "123456";
        String encryptedPassword = MD5Util.encrypt(password);
        SysUser sysUser = SysUser.builder()
                .username(sysUserBO.getUsername())
                .telephone(sysUserBO.getTelephone())
                .mail(sysUserBO.getMail())
                .password(encryptedPassword)
                .deptId(sysUserBO.getDeptId())
                .status(sysUserBO.getStatus())
                .remark(sysUserBO.getRemark())
                .build();

//        sysUser.setOperator("system");// TODO
        sysUser.setOperator(RequestHolder.getCurrentUser().getUsername());// 取出当前登录用户
        sysUser.setOperateIp("127.0.0.1");// TODO
        sysUser.setOperateTime(new Date());

        // TODO 发送Email成功之后才能进行更新操作
        sysUserMapper.insertSelective(sysUser);

        SysUserVO vo = new SysUserVO();
        BeanUtils.copyProperties(sysUser, vo);

        return vo;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Optional<Integer> delete(Integer userId) {
        Preconditions.checkNotNull(userId, "userId空");
        int i = sysUserMapper.deleteByPrimaryKey(userId);
        return Optional.ofNullable(i);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public SysUserVO update(SysUserBO sysUserBO) {
        BeanValidator.check(sysUserBO);
        if (checkTelephoneExist(sysUserBO.getTelephone(), sysUserBO.getId())) {
            throw new ParamException("移动电话已被占用");
        }
        if (checkEmailExist(sysUserBO.getMail(), sysUserBO.getId())) {
            throw new ParamException("邮箱已被占用");
        }
        SysUser before = sysUserMapper.selectByPrimaryKey(sysUserBO.getId());
        Preconditions.checkNotNull(before, "待更新的用户不存在");
        SysUser after = SysUser.builder()
                .id(sysUserBO.getId())
                .username(sysUserBO.getUsername())
                .telephone(sysUserBO.getTelephone())
                .mail(sysUserBO.getMail())
                .password(before.getPassword())
                .deptId(sysUserBO.getDeptId())
                .status(sysUserBO.getStatus())
                .remark(sysUserBO.getRemark())
                .build();
        // after.setOperator("system");// TODO
        after.setOperator(RequestHolder.getCurrentUser().getUsername());// 取出当前登录用户
        after.setOperateIp("127.0.0.1");// TODO
        after.setOperateTime(new Date());
        sysUserMapper.updateByPrimaryKeySelective(after);

        SysUserVO vo = new SysUserVO();
        BeanUtils.copyProperties(after, vo);
        return vo;
    }

    /**
     * 切花用户状态
     *
     * @param userId
     * @param status
     */
    @Override
    public void activeUser(Integer userId, Integer status) {
        Preconditions.checkNotNull(userId, "用户id空");
        Preconditions.checkNotNull(status, "状态空");

        SysUser sysUser = SysUser.builder().id(userId).status(status).build();
        sysUserMapper.updateByPrimaryKeySelective(sysUser);

    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Optional<SysUserVO> findByKeyword(String keyword) {
        Optional<SysUserVO> userOptional = Optional.ofNullable(sysUserCustomMapper.findByKeyword(keyword));
        return userOptional;
    }

    @Override
    public Optional<SysUser> findOne(Integer userId) {
        Preconditions.checkNotNull(userId, "无userId");
        Optional<SysUser> sysUserOptional = Optional.ofNullable(sysUserMapper.selectByPrimaryKey(userId));
        return sysUserOptional;
    }

    @Override
    public PagedGridResult getAll(Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);
        List<SysUser> sysUserList = sysUserMapper.selectAll();
        List<UserVO> usersDetailed = sysUserCustomMapper.getUsersDetailed();
        List<Object> collect = usersDetailed.stream().map(userVO -> {
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            userVO.setOperateTimeFormat(df.format(userVO.getOperateTime()));
            return userVO;
        }).collect(Collectors.toList());

        // TODO 根据用户获取，涉及权限，例如项目主管获取项目所有人
//        Example example = new Example(ArchProject.class);
//        Example.Criteria criteria = example.createCriteria();
//        criteria.andEqualTo("managerId", userId);// 当前用户匹配项目管理员
//        List<ArchProject> archProjectList = archProjectMapper.selectByExample(example);
//        List<Integer> archProjectManagerIdList = archProjectList.stream().map(archProject -> archProject.getManagerId()).collect(Collectors.toList());
//        Set<Integer> archProjectManagerIdSet = new HashSet<>();// 项目管理员Set
//        if (!CollectionUtils.isEmpty(archProjectList)) {
//            // 业务：存在当前用户为管理员的的项目，获取项目下的用户详情
//            for (Integer managerId : archProjectManagerIdList) {
//                archProjectManagerIdSet.add(managerId);
//            }
//            // 获取到匹配项目信息
//            List<ArchProject> matchedUserIdProjectList = archProjectList.stream().filter(archProject -> archProject.getManagerId() == userId).collect(Collectors.toList());
//
//        }
        return setPagesGrid(collect, page);
    }

    @Override
    public List<SysUser> getAll() {
        return sysUserMapper.selectAll();
    }

    @Override
    public List<SysUser> getUsersByDeptId(Integer deptId) {
        Example example = new Example(SysUser.class);
        example.orderBy("username").asc();
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("deptId", deptId);
        List<SysUser> sysUsers = sysUserMapper.selectByExample(example);
        return sysUsers;
    }

    @Override
    public SysUser searchUserById(Integer userId) {
        Example example = new Example(SysUser.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("id", userId);
        criteria.andEqualTo("status", UserStatusEnum.NORMAL.ordinal());
        SysUser sysUser = sysUserMapper.selectOneByExample(example);
        return sysUser;
    }

    /**
     * 根据用户id批量获取用户
     *
     * @param userIdList
     * @return
     */
    @Override
    public Optional<List<SysUserVO>> searchUsersByIdList(List<Integer> userIdList) {
        Optional<List<SysUserVO>> userByUserIdListOptional = Optional.ofNullable(sysUserCustomMapper.getUserByUserIdList(userIdList));
        return null;
    }

    /**
     * 微信注册
     *
     * @param wxRegisterBO
     * @return
     */
    @Override
    public Optional<List<SysUser>> wxRegister(WxRegisterBO wxRegisterBO) {
        if (StringUtils.isBlank(wxRegisterBO.getCode())) throw new ParamException("code空");
        Preconditions.checkNotNull(wxRegisterBO, "注册信息有误");

        // 获取openId
        String openId = getOpenId(wxRegisterBO.getCode());

        // 查询用户
        Optional<List<SysUser>> userOptionalBefore = Optional.ofNullable(sysUserMapper.getUserByOpenId(openId));
        List<SysUser> usersByOpenId = userOptionalBefore.orElseThrow(() -> new ParamException("没有对应openId的用户"));

        Integer userId = null;
        if (usersByOpenId.size() >= 1) {
            SysUser tempySysUser = usersByOpenId.stream().findFirst().orElseThrow(() -> new ParamException("无用户id"));
            userId = tempySysUser.getId();
//            throw new ParamException("已存在，等待审核");
        } else if (CollectionUtils.isEmpty(usersByOpenId)) {
            // openid无对应用户，则执行注册
            SysUser sysUser = SysUser.builder()
                    .openId(openId)
                    .nickname(wxRegisterBO.getNickname())
                    .status(0)// 未激活
                    .telephone(wxRegisterBO.getMobile())
                    .nickname(wxRegisterBO.getNickname())
                    .avatar(wxRegisterBO.getAvatar())
                    .operateTime(new Date())
                    .operator("张进")
                    .operateIp("127.0.0.1")
                    .build();
            sysUserMapper.insert(sysUser);
            List<SysUser> userByOpenId = sysUserMapper.getUserByOpenId(openId);
            SysUser tempySysUser = userByOpenId.stream().findFirst().orElseThrow(() -> new ParamException("无用户id"));
            userId = tempySysUser.getId();
        }

        // 项目楼栋用户
        Example example = new Example(ArchProjectBuildingUser.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("projectId", wxRegisterBO.getProjectId());
        criteria.andEqualTo("buildingId", wxRegisterBO.getBuildingId());
        criteria.andEqualTo("userId", userId);
        int count = archProjectBuildingUserMapper.selectCountByExample(example);
        if (count < 1) {
            ArchProjectBuildingUser archProjectBuildingUser = ArchProjectBuildingUser.builder()
                    .projectId(wxRegisterBO.getProjectId())
                    .buildingId(wxRegisterBO.getBuildingId())
                    .userId(userId)
                    .status(ProjectBuildingUserStatusEnum.NO_AUDIT.ordinal())// 默认不激活
                    .operateIp("127.0.0.1")
                    .operator("张进")
                    .operateTime(new Date())
                    .build();
            Integer insert = archProjectBuildingUserMapper.insert(archProjectBuildingUser);
        } else {
            throw new ParamException("该楼栋已绑定");
        }

        return Optional.ofNullable(sysUserMapper.getUserByOpenId(openId));
    }

    private String getOpenId(String code) {
        String url = "https://api.weixin.qq.com/sns/jscode2session";
        HashMap map = new HashMap();
        map.put("appid", appId);
        map.put("secret", appSecret);
        map.put("js_code", code);
        map.put("grant_type", "authorization_code");
        String response = HttpUtil.post(url, map);
        JSONObject json = JSONUtil.parseObj(response);
        String openId = json.getStr("openid");
        if (openId == null || openId.length() == 0) {
            throw new RuntimeException("临时登陆凭证错误");
        }
        return openId;
    }

    /**
     * 校验邮箱是否存在
     *
     * @param mail
     * @param userId
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    public boolean checkEmailExist(String mail, Integer userId) {
        return sysUserCustomMapper.countByMail(mail, userId) > 0;
    }

    /**
     * 校验移动电话是否存在
     *
     * @param telephone
     * @param userId
     * @return
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    public boolean checkTelephoneExist(String telephone, Integer userId) {
        return sysUserCustomMapper.countByTelephone(telephone, userId) > 0;
    }

    /**
     * 封装分页助手
     *
     * @param list
     * @param page
     * @return
     */
    private PagedGridResult setPagesGrid(List<?> list, Integer page) {
        PageInfo pageList = new PageInfo<>(list);
        PagedGridResult grid = new PagedGridResult();
        grid.setPage(page);
        grid.setRows(list);
        grid.setTotal(pageList.getPages());
        grid.setRecords(pageList.getTotal());
        return grid;
    }
}
